from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login, logout
from django.http import HttpResponse, JsonResponse
from .models import EnvironmentData, CardData, CardList
from django.contrib.auth.models import User
import json
from djangoProject.mqtt import mqtt_client
from django.db import transaction  # 已存在的导入
from django.utils import timezone

def login_view(request):
    if request.method == 'POST':
        # 添加登录验证逻辑
        username = request.POST.get('username')
        password = request.POST.get('password')
        user = authenticate(request, username=username, password=password)
        if user is not None:
            login(request, user)
            return redirect('back:dashboard')
        else:
            # 添加登录失败的错误提示
            return render(request, 'back/login.html', {'error': '用户名或密码错误'})
    return render(request, 'back/login.html')




def register_view(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password1 = request.POST.get('password1')
        password2 = request.POST.get('password2')
        
        # 添加输入验证
        if not username or not password1 or not password2:
            return render(request, 'back/register.html', {'error': '所有字段都必须填写'})
        
        if password1 != password2:
            return render(request, 'back/register.html', {'error': '密码不匹配'})
        
        # 检查用户名是否已存在
        if User.objects.filter(username=username).exists():
            return render(request, 'back/register.html', {'error': '用户名已存在'})
        
        # 创建用户
        user = User.objects.create_user(username=username, password=password1)
        
        # 自动登录用户
        user = authenticate(username=username, password=password1)
        login(request, user)
        
        # 注册成功后重定向到登录页面
        return redirect('login')
    
    return render(request, 'back/register.html')

#


def dashboard_view(request):
    if not request.user.is_authenticated:
        return redirect('login')
    
    # 获取最新的环境数据和卡片数据
    environment_data = EnvironmentData.objects.all().order_by('-timestamp')[:10]
    card_data = CardData.objects.all().order_by('-timestamp')[:50]  # 增加到50条
    
    context = {
        'environment_data': environment_data,
        'card_data': card_data,
        'username': request.user.username,
    }
    
    return render(request, 'back/dashboard.html', context)


def write_card(request):
    if not request.user.is_authenticated:
        return redirect('login')
        
    if request.method == 'POST':
        card_number = request.POST.get('card_number')
        information = request.POST.get('information')
        
        # 添加输入验证
        if not card_number or not information:
            return render(request, 'back/write_card.html', {'error': '卡号和信息都必须填写'})
        
        # 去除卡号中可能的空格和格式化字符，确保格式与ESP32端一致
        card_number = card_number.strip().upper()
        
        data = {'card_number': card_number, 'information': information}
        payload = json.dumps(data)

        try:
            # 发布到 MQTT 主题
            rc, mid = mqtt_client.client.publish('/writecard', payload)
            print(f"发送卡片数据到MQTT: {payload}")
            
            # 保存到数据库
            card = CardData.objects.create(
                card_number=card_number, 
                information=information,
                is_registered=True
            )
            
            return render(request, 'back/write_card.html', {
                'success': f'数据成功发送至 MQTT 主题 /writecard! 卡号: {card_number}',
                'card': card
            })

        except Exception as e:
            return render(request, 'back/write_card.html', {'error': f'无法发布数据到 MQTT: {str(e)}'})

    return render(request, 'back/write_card.html', {'username': request.user.username})

def read_card(request):
    if not request.user.is_authenticated:
        return redirect('login')

    # 获取最新的卡片数据
    card_data = CardData.objects.all().order_by('-timestamp')[:10]
    
    return render(request, 'back/dashboard.html', {
        'card_data': card_data,  # 添加卡片数据到上下文
        'environment_data': EnvironmentData.objects.all(),
    })

def send_mqtt_message(request):
    if request.method == 'POST':
        try:
            request_data = json.loads(request.body)
            topic = request_data.get('topic')
            message = request_data.get('message')
            if not topic or not message:
                return JsonResponse({'status': 'invalid parameters'}, status=400)
                
            # 修复此处调用方式，通过client属性访问
            rc, mid = mqtt_client.client.publish(topic, message)
            return JsonResponse({'status': 'success', 'rc': rc})
        except json.JSONDecodeError as e:
            return JsonResponse({'status': 'error', 'message': f'Invalid JSON: {str(e)}'}, status=400)
        except Exception as e:
            return JsonResponse({'status': 'error', 'message': str(e)}, status=500)

def door_control(request):
    if request.method == 'POST':
        try:
            data = json.loads(request.body)
            action = data.get('action')
            value = data.get('value')
            
            # 添加输入验证
            if not action:
                return JsonResponse({'status': 'error', 'message': '缺少必要参数'}, status=400)
                
            payload = json.dumps({
                'action': action,
                'value': value
            })
            
            rc, mid = mqtt_client.client.publish('/door', payload)
            
            return JsonResponse({
                'status': 'success', 
                'rc': rc, 
                'message': f'门禁控制命令已发送: {action}'
            })
        except Exception as e:
            return JsonResponse({'status': 'error', 'message': str(e)}, status=400)
    
    # 如果是GET请求，返回门禁控制页面
    if request.method == 'GET' and request.user.is_authenticated:
        return render(request, 'back/door_control.html', {'username': request.user.username})
        
    return JsonResponse({'status': 'method not allowed'}, status=405)


def logout_view(request):
    logout(request)
    return redirect('login')


def write_finger(request):
    if not request.user.is_authenticated:
        return redirect('login')
    
    if request.method == 'POST':
        user_id = request.POST.get('user_id')
        user_name = request.POST.get('user_name', '')
        
        # 添加输入验证
        if not user_id:
            return render(request, 'back/write_finger.html', {
                'error': '用户ID必须填写',
                'username': request.user.username
            })
            
        try:
            # 准备MQTT发布数据
            payload = json.dumps({
                'user_id': user_id,
                'user_name': user_name,
                'action': 'enroll'
            })
            rc, mid = mqtt_client.client.publish('/fingerprint', payload)
            
            return render(request, 'back/write_finger.html', {
                'success': f'指纹录入请求已发送，用户ID: {user_id}',
                'username': request.user.username
            })
        except Exception as e:
            return render(request, 'back/write_finger.html', {
                'error': f'操作失败: {str(e)}',
                'username': request.user.username
            })
    
    return render(request, 'back/write_finger.html', {'username': request.user.username})

def write_password(request):
    if not request.user.is_authenticated:
        return redirect('login')
        
    if request.method == 'POST':
        user_id = request.POST.get('user_id')
        password = request.POST.get('password')
        confirm_password = request.POST.get('confirm_password')
        
        # 添加输入验证
        if not user_id or not password or not confirm_password:
            return render(request, 'back/write_password.html', {
                'error': '所有字段都必须填写',
                'username': request.user.username
            })
            
        if password != confirm_password:
            return render(request, 'back/write_password.html', {
                'error': '两次输入的密码不匹配',
                'username': request.user.username
            })
            
        try:
            # 准备MQTT发布数据
            payload = json.dumps({
                'user_id': user_id,
                'password': password,
                'action': 'set_password'
            })
            rc, mid = mqtt_client.client.publish('/password', payload)
            
            return render(request, 'back/write_password.html', {
                'success': f'密码设置请求已发送，用户ID: {user_id}',
                'username': request.user.username
            })
        except Exception as e:
            return render(request, 'back/write_password.html', {
                'error': f'操作失败: {str(e)}',
                'username': request.user.username
            })
    
    return render(request, 'back/write_password.html', {'username': request.user.username})


def get_rfid_info(request):
    if not request.user.is_authenticated:
        return JsonResponse({'status': 'unauthorized'}, status=401)
    
    # 处理录入模式
    if request.method == 'POST' and request.GET.get('mode') == 'enroll':
        try:
            # 获取前端传来的持卡人信息
            information = request.POST.get('information', '').strip()
            
            if not information:
                return JsonResponse({
                    'status': 'error',
                    'card_detected': False,
                    'error': '请输入持卡人姓名'
                })
            
            # 通过MQTT获取当前卡片数据（此处实际上应该与硬件通信）
            card_data = CardData.objects.all().order_by('-timestamp').first()
            
            if card_data:
                # 更新卡片信息
                card_data.information = information
                card_data.is_registered = True
                card_data.save()
                
                print(f"卡片 {card_data.card_number} 已成功录入持卡人信息: {information}")
                
                # 创建一个新的记录，存储这次录入操作
                CardData.objects.create(
                    card_number=card_data.card_number,
                    information=information,
                    is_registered=True,
                    timestamp=timezone.now()
                )
                
                # 发送录入信息到MQTT，通知ESP32
                try:
                    mqtt_data = {
                        'card_number': card_data.card_number,
                        'information': information
                    }
                    mqtt_client.client.publish('/writecard', json.dumps(mqtt_data))
                    print(f"已发送卡片录入信息到MQTT: {mqtt_data}")
                except Exception as e:
                    print(f"MQTT发送失败: {str(e)}")
                
                return JsonResponse({
                    'status': 'success',
                    'card_detected': True,
                    'uid': card_data.card_number,
                    'card_type': 'MIFARE Classic',
                    'read_time': card_data.timestamp.strftime('%Y-%m-%d %H:%M:%S'),
                    'is_registered': True,
                    'enroll_success': True
                })
            else:
                return JsonResponse({
                    'status': 'error',
                    'card_detected': False,
                    'error': '未检测到卡片'
                })
        except Exception as e:
            return JsonResponse({
                'status': 'error',
                'card_detected': False,
                'error': str(e)
            })
    
    # 读取模式 - 返回所有卡片数据供前端显示
    elif request.method == 'GET':
        card_data = CardData.objects.all().order_by('-timestamp')[:50]  # 增加到50条
        data = [{
            "card_number": item.card_number,
            "card_type": "MIFARE Classic",
            "information": item.information,
            "timestamp": item.timestamp.isoformat(),
            "is_registered": item.is_registered  # 使用数据库中的is_registered字段
        } for item in card_data]
        
        # 如果是实时查询模式，返回最新一条记录的详细信息
        if request.GET.get('mode') == 'realtime':
            latest_card = CardData.objects.all().order_by('-timestamp').first()
            if latest_card:
                return JsonResponse({
                    'status': 'success',
                    'card_detected': True,
                    'uid': latest_card.card_number,
                    'card_type': 'MIFARE Classic',
                    'read_time': latest_card.timestamp.strftime('%Y-%m-%d %H:%M:%S'),
                    'is_registered': latest_card.is_registered
                })
            else:
                return JsonResponse({
                    'status': 'error',
                    'card_detected': False
                })
        
        return JsonResponse(data, safe=False)
    
    return JsonResponse({'status': 'method not allowed'}, status=405)


def receive_card_data(request):
    if request.method == 'POST':
        try:
            data = json.loads(request.body)
            card_id = data.get('card_id')
            information = data.get('information')
            
            # 添加事务控制
            with transaction.atomic():
                CardData.objects.create(
                    card_id=card_id,
                    information=information,
                    timestamp=timezone.now()
                )
                
            return JsonResponse({'status': 'success'})
            
        except Exception as e:
            return JsonResponse({'status': 'error', 'message': str(e)})
    return JsonResponse({'status': 'method not allowed'}, status=405)


def handle_mqtt_card_list(client, userdata, msg):
    """处理从MQTT接收到的卡片列表"""
    try:
        print(f"收到卡片列表消息，主题: {msg.topic}")
        # 解析JSON数据
        data = msg.payload.decode('utf-8')
        print(f"卡片列表数据: {data}")
        
        # 保存到数据库
        CardList.objects.create(data=data, timestamp=timezone.now())
        print(f"已保存卡片列表到数据库")
    except Exception as e:
        print(f"处理卡片列表消息出错: {str(e)}")

# 修改现有的handle_mqtt_message函数进行分发
def handle_mqtt_message(client, userdata, msg):
    print(f"收到MQTT消息，主题: {msg.topic}")
    
    # 根据主题分发处理
    if msg.topic == '/cardID':
        try:
            data = json.loads(msg.payload.decode())
            card_number = data.get('card_id')
            # 自动获取信息部分由information替换为空字符串，避免覆盖持卡人信息
            information = ""
            
            # 查找卡片是否已注册以及持卡人信息
            is_registered = False
            existing_card = CardData.objects.filter(
                card_number=card_number, 
                is_registered=True
            ).order_by('-timestamp').first()
            
            if existing_card and existing_card.information:
                is_registered = True
                information = existing_card.information
                print(f"找到已注册卡片信息: {card_number} - {information}")
            else:
                print(f"卡片 {card_number} 未注册或无持卡人信息")
            
            # 保存到数据库
            CardData.objects.create(
                card_number=card_number,
                information=information,  # 使用查找到的持卡人信息
                timestamp=timezone.now(),
                is_registered=is_registered
            )
            print(f"已保存刷卡数据: {card_number}, 持卡人: {information or '未知'}")
        except Exception as e:
            print(f"处理cardID消息出错: {str(e)}")
    elif msg.topic == '/cardlist':
        handle_mqtt_card_list(client, userdata, msg)
        print(f"已分派到handle_mqtt_card_list处理")
    else:
        print(f"未知主题: {msg.topic}，无法处理")

# 确保MQTT订阅了cardlist主题
mqtt_client.client.on_message = handle_mqtt_message
mqtt_client.client.subscribe("/readcard")
mqtt_client.client.subscribe("/cardlist")  # 订阅卡片列表主题

def get_card_list(request):
    """获取最新的卡片列表"""
    if not request.user.is_authenticated:
        return JsonResponse({'status': 'unauthorized'}, status=401)
    
    # 获取最新的卡片列表
    try:
        latest_card_list = CardList.objects.latest('timestamp')
        return JsonResponse(json.loads(latest_card_list.data))
    except CardList.DoesNotExist:
        return JsonResponse({'count': 0, 'cards': []})
    except Exception as e:
        return JsonResponse({'error': str(e)}, status=500)